﻿using System.Collections;
using UnityEngine;
using static ZXthex.CutMesh;

/// <summary>
/// 
/// Demo:
/// 
///     切开带有MeshCollider和Rigidbody的物体，并生成切开物体的横截面物体，横截面使用提供的材质着色。
///     
/// </summary>
public class SplitAway : MonoBehaviour
{
    [Tooltip("使用的拖尾效果")]
    public TrailRenderer tr;

    [Tooltip("内面使用的材质球")]
    public Material material;

    [Tooltip("切开所形成的纵向撞击力")]
    public float slashForce = 66.6f;

    [Tooltip("一次按下鼠标只允许切开一个物体")]
    public bool oneCut = true;

    [Tooltip("生成碎块的父物体")]
    public Transform world;

    Vector3 lastPosOfMouse; 

    float slash_cd; 

    void Update()
    {

        if (Input.GetMouseButtonDown(0))
        {
            slash_cd = 0;
            tr.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition + Vector3.forward);
            tr.Clear();

            lastPosOfMouse = Input.mousePosition;
        }
        if (Input.GetMouseButton(0))
        {
            slash_cd -= Time.deltaTime;

            var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            tr.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition + Vector3.forward);

            Vector3[] poses = new Vector3[tr.positionCount];
            tr.GetPositions(poses);
            if (slash_cd<=0)
            {
                if (Physics.Raycast(mouseRay, out RaycastHit rH, 100f))
                {
                    if (rH.rigidbody && rH.collider is MeshCollider mc)
                    {
                        var delt = Input.mousePosition - lastPosOfMouse;
                        if (delt.sqrMagnitude > 1)
                        {
                            Vector3 planeNormal = Vector3.Cross(Vector3.forward, delt).normalized;
                            CutMesh(mc, rH.point, planeNormal);
                            slash_cd = oneCut? float.MaxValue: 0.04f;
                        }
                    }
                }
            }

            lastPosOfMouse = Input.mousePosition;

        }

    }



    GameObject[] CutMesh(MeshCollider mc, Vector3 planePointWorld, Vector3 planeNormalWorld)
    {
        MeshFilter meshFilter = mc.transform.GetChild(0).GetComponent<MeshFilter>();

        CutAMesh(meshFilter, planePointWorld, planeNormalWorld, out Mesh mesh1, out Mesh mesh2,
                        out Mesh fill1, out Mesh fill2);

        var mc1 = Instantiate(mc, world);

        var mf1 = mc1.transform.GetChild(0).GetComponent<MeshFilter>();
        mf1.mesh = mesh1;

        var mc2 = Instantiate(mc, world);

        var mf2 = mc2.transform.GetChild(0).GetComponent<MeshFilter>();
        mf2.mesh = mesh2;

        void ClearTransform(Transform trans)
        {
            trans.localPosition = new Vector3();
            trans.localEulerAngles = new Vector3();
            trans.localScale = Vector3.one;
        }

        GameObject f1 = new GameObject("fill");
        f1.AddComponent<MeshFilter>().mesh = fill1;
        f1.AddComponent<MeshRenderer>().material = material;
        f1.transform.SetParent(mf1.transform);
        ClearTransform(f1.transform);


        GameObject f2 = new GameObject("fill");
        f2.AddComponent<MeshFilter>().mesh = fill2;
        f2.AddComponent<MeshRenderer>().material = material;
        f2.transform.SetParent(mf2.transform);
        ClearTransform(f2.transform);

        CutAMesh(mc, planePointWorld, planeNormalWorld, out var m1, out var m2);

        mc1.sharedMesh = m1;
        mc2.sharedMesh = m2;

        mf1.transform.SetParent(mc1.transform);
        ClearTransform(mf1.transform);
        mf2.transform.SetParent(mc2.transform);
        ClearTransform(mf2.transform);

        if (mc.GetComponent<Rigidbody>())
        {
            IEnumerator DelayCall()
            {
                var rb1 = mc1.GetComponent<Rigidbody>();
                var rb2 = mc2.GetComponent<Rigidbody>();

                rb1.MovePosition(planeNormalWorld * 0.01f + rb1.transform.position);
                rb2.MovePosition(-planeNormalWorld * 0.01f + rb2.transform.position);

                rb1.AddForce(planeNormalWorld * slashForce);
                rb2.AddForce(-planeNormalWorld * slashForce);

                mc1.enabled = false;
                mc2.enabled = false;
                yield return new WaitForFixedUpdate();
                mc1.enabled = true;
                mc2.enabled = true;
            }
            StartCoroutine(DelayCall());
        }


        for (int i = 0; i < meshFilter.transform.childCount; i++)
        {
            mf1.transform.GetChild(i).gameObject.SetActive(false);
            mf2.transform.GetChild(i).gameObject.SetActive(false);
        }

        meshFilter.transform.parent.gameObject.SetActive(false);

        return new GameObject[] { mf1.gameObject, mf2.gameObject };
    }

    
}


